package main

import (
        "encoding/json"
        "flag"
        "fmt"
        "os"
        // "strconv"
        "time"
)

// Todo 单个待办事项的结构体
type Todo struct {
        ID        int       `json:"id"`        // 唯一ID（用于标记/删除）
        Content   string    `json:"content"`   // 待办内容
        Completed bool      `json:"completed"` // 完成状态
        CreatedAt time.Time `json:"createdAt"` // 创建时间
}

// TodoList 待办列表（本质是Todo切片）
type TodoList []Todo

// 数据文件路径（固定在项目根目录）
const dataFile = "todos.json"

// loadTodos 从文件加载待办数据到内存
func loadTodos() (TodoList, error) {
	// 1. 尝试打开文件（若文件不存在，返回空列表+无错误）
	file, err := os.Open(dataFile)
	if err != nil {
		if os.IsNotExist(err) { // 文件不存在是正常初始状态
			return TodoList{}, nil
		}
		return nil, fmt.Errorf("打开文件失败：%w", err) // 其他错误返回
	}
	defer file.Close() // 函数结束前关闭文件（避免资源泄漏）

	// 2. 从文件中读取JSON数据并解析到TodoList
	var todos TodoList
	decoder := json.NewDecoder(file)
	if err := decoder.Decode(&todos); err != nil {
		return nil, fmt.Errorf("解析JSON失败：%w", err)
	}

	return todos, nil
}

// saveTodos 将内存中的待办数据写入文件
func saveTodos(todos TodoList) error {
	// 1. 创建文件（若文件存在则覆盖）
	file, err := os.Create(dataFile)
	if err != nil {
		return fmt.Errorf("创建文件失败：%w", err)
	}
	defer file.Close()

	// 2. 将TodoList序列化为JSON并写入文件（带缩进，方便人读）
	encoder := json.NewEncoder(file)
	encoder.SetIndent("", "  ") // JSON缩进格式（美观）
	if err := encoder.Encode(todos); err != nil {
		return fmt.Errorf("写入JSON失败：%w", err)
	}

	return nil
}

// generateID 生成唯一ID（取当前列表最大ID+1，避免重复）
func generateID(todos TodoList) int {
        maxID := 0
        for _, todo := range todos {
                if todo.ID > maxID {
                        maxID = todo.ID
                }
        }
        return maxID + 1
}

// addTodo 添加新待办
func addTodo(todos *TodoList, content string) error {
        // 1. 构造新待办
        newTodo := Todo{
                ID:        generateID(*todos),
                Content:   content,
                Completed: false,
                CreatedAt: time.Now(), // 获取当前时间
        }

        // 2. 将新待办追加到列表
        *todos = append(*todos, newTodo)

        // 3. 保存到文件
        return saveTodos(*todos)
}

// listTodos 查看所有待办（按创建时间升序）
func listTodos(todos TodoList) {
        if len(todos) == 0 {
                fmt.Println("✅ 暂无待办事项，快去添加第一个吧！")
                return
        }

        // 遍历输出（格式化状态：已完成标✅，未完成标🔄）
        fmt.Println("📋 你的待办列表：")
        for _, todo := range todos {
                status := "🔄 未完成"
                if todo.Completed {
                        status = "✅ 已完成"
                }
                // 时间格式化：2006-01-02 15:04:05（Go的固定时间模板）
                fmt.Printf("ID: %d | %s | 内容：%s | 创建时间：%s\n",
                        todo.ID, status, todo.Content, todo.CreatedAt.Format("2006-01-02 15:04:05"))
        }
}

// completeTodo 标记待办为完成
func completeTodo(todos *TodoList, id int) error {
        // 遍历列表查找ID匹配的待办
        found := false
        for i, todo := range *todos {
                if todo.ID == id {
                        (*todos)[i].Completed = true // 修改状态
                        found = true
                        break
                }
        }

        if !found {
                return fmt.Errorf("未找到ID为 %d 的待办", id)
        }

        // 保存到文件
        return saveTodos(*todos)
}

// deleteTodo 删除指定ID的待办
func deleteTodo(todos *TodoList, id int) error {
        // 遍历列表查找ID索引
        index := -1
        for i, todo := range *todos {
                if todo.ID == id {
                        index = i
                        break
                }
        }

        if index == -1 {
                return fmt.Errorf("未找到ID为 %d 的待办", id)
        }

        // 切片删除逻辑：将index前后的元素拼接（Go切片无直接删除方法）
        *todos = append((*todos)[:index], (*todos)[index+1:]...)

        // 保存到文件
        return saveTodos(*todos)
}

func main() {
        // 1. 从文件加载已有待办（程序启动先读数据）
        todos, err := loadTodos()
        if err != nil {
                fmt.Printf("❌ 初始化失败：%v\n", err)
                os.Exit(1) // 错误退出（状态码1表示异常）
        }

        // 2. 解析命令行参数（flag包：定义子命令）
        addCmd := flag.NewFlagSet("add", flag.ExitOnError)
        listCmd := flag.NewFlagSet("list", flag.ExitOnError)
        completeCmd := flag.NewFlagSet("complete", flag.ExitOnError)
        deleteCmd := flag.NewFlagSet("delete", flag.ExitOnError)

        // 为子命令绑定参数（如add命令需要接收待办内容）
        addContent := addCmd.String("content", "", "待办内容（必填）")
        completeID := completeCmd.Int("id", 0, "待办ID（必填）")
        deleteID := deleteCmd.Int("id", 0, "待办ID（必填）")

        // 3. 检查用户是否输入了命令（如用户直接运行./todo，无命令则提示）
        if len(os.Args) < 2 {
                fmt.Println("❌ 请输入命令：add/list/complete/delete")
                fmt.Println("示例：")
                fmt.Println("  ./todo add -content \"买牛奶\"")
                fmt.Println("  ./todo list")
                fmt.Println("  ./todo complete -id 1")
                fmt.Println("  ./todo delete -id 1")
                os.Exit(1)
        }

        // 4. 根据用户输入的命令，执行对应逻辑
        switch os.Args[1] {
        case "add":
                // 解析add命令的参数（如-content）
                addCmd.Parse(os.Args[2:])
                // 校验必填参数（内容不能为空）
                if *addContent == "" {
                        fmt.Println("❌ 请用 -content 指定待办内容")
                        addCmd.Usage() // 显示命令用法提示
                        os.Exit(1)
                }
                // 执行添加逻辑
                if err := addTodo(&todos, *addContent); err != nil {
                        fmt.Printf("❌ 添加失败：%v\n", err)
                        os.Exit(1)
                }
                fmt.Printf("✅ 待办添加成功！内容：%s\n", *addContent)

        case "list":
                // 解析list命令（无额外参数）
                listCmd.Parse(os.Args[2:])
                // 执行查看逻辑
                listTodos(todos)

        case "complete":
                // 解析complete命令的参数（-id）
                completeCmd.Parse(os.Args[2:])
                // 校验ID（不能为0）
                if *completeID == 0 {
                        fmt.Println("❌ 请用 -id 指定待办ID")
                        completeCmd.Usage()
                        os.Exit(1)
                }
                // 执行标记完成逻辑
                if err := completeTodo(&todos, *completeID); err != nil {
                        fmt.Printf("❌ 标记失败：%v\n", err)
                        os.Exit(1)
                }
                fmt.Printf("✅ ID为 %d 的待办已标记为完成！\n", *completeID)

        case "delete":
                // 解析delete命令的参数（-id）
                deleteCmd.Parse(os.Args[2:])
                // 校验ID
                if *deleteID == 0 {
                        fmt.Println("❌ 请用 -id 指定待办ID")
                        deleteCmd.Usage()
                        os.Exit(1)
                }
                // 执行删除逻辑
                if err := deleteTodo(&todos, *deleteID); err != nil {
                        fmt.Printf("❌ 删除失败：%v\n", err)
                        os.Exit(1)
                }
                fmt.Printf("✅ ID为 %d 的待办已删除！\n", *deleteID)

        default:
                // 未知命令提示
                fmt.Printf("❌ 未知命令：%s\n", os.Args[1])
                os.Exit(1)
        }
}
